﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Configuration;
using System.IO;

namespace Maspalomas
{
   public partial class Form1 : Form
   {
      FakeLogger logger;
      public const string c_tempFilename = "temp_data.xml";
      
      public string BackupPath
      {
         get { return ConfigurationManager.AppSettings["backupPath"] + "Maspalomas_backup.sql"; }
      }
       
      public string ExportImportPath
      {
         get { return ConfigurationManager.AppSettings["OfflineExchangeRepository"] + "Maspalomas_export.sql"; }
      }

      OdbcDSConnection m_conn = null;
      public OdbcDSConnection Conn
      {
         get
         {
            if (m_conn != null)
               return m_conn;
            else
            {
               m_conn = new OdbcDSConnection();
               //m_conn.OpenConnection("PostgreSQL35W", "", "", logger);
               m_conn.OpenConnectionDefault(logger);
            }
            return m_conn;
         }
      }

      public Form1()
      {
         InitializeComponent();
         txtDate.Text = DateTime.Today.Day.ToString();
         txtDate.Select();

         InitializeListItems(cmbPayment, "Payment_Items");
         InitializeListItems(cmbCategory, "Category_Items");
         InitializeListItems(cmbSubcategory, "SubCategory_Items");
         InitializeListItems(cmbComment1, "Comment1_Items");
         InitializeListItems(cmbComment2, "Comment2_Items");

         this.Text = "Maspalomas " + Program.Version;
      }

      private void InitializeListItems(ComboBox cmb, string appKey)
      {
         string keyValue = ConfigurationManager.AppSettings[appKey];
         if (string.IsNullOrEmpty(keyValue))
            return;

         string[] arrValue = keyValue.Split(',');
         foreach (string item in arrValue)
            cmb.Items.Add(item);
      }

      private void btnAdd_Click(object sender, EventArgs e)
      {
         DataRow dr = dataSet1.Tables["Expenses"].NewRow();
         dr["Payment"] = cmbPayment.Text;
         dr["Date"] = BuildDate(txtDate.Text);
         dr["Amount"] = double.Parse(txtAmount.Text);
         dr["Category"] = cmbCategory.Text;
         dr["SubCategory"] = cmbSubcategory.Text;
         dr["Comment1"] = cmbComment1.Text;
         dr["Comment2"] = cmbComment2.Text;
         
         dataSet1.Tables["Expenses"].Rows.Add(dr);

         ClearFields();
      }

      private void ClearFields()
      {
         if (!chkPayment.Checked)
            cmbPayment.Text = string.Empty;
         if (!chkDate.Checked)
            txtDate.Text = string.Empty;
         if (!chkAmount.Checked)
            txtAmount.Text = string.Empty;
         if (!chkCategory.Checked)
            cmbCategory.Text = string.Empty;
         if (!chkSubCategory.Checked)
            cmbSubcategory.Text = string.Empty;
         if (!chkComment1.Checked)
            cmbComment1.Text = string.Empty;
         if (!chkComment2.Checked)
            cmbComment2.Text = string.Empty;
      }

      private DateTime BuildDate(string strDate)
      {
         char[] dateSeparators = { '-', ',' };

         DateTime dt = DateTime.Today;
         if (strDate.Length > 0)
         {
            string[] arr = strDate.Split(dateSeparators);
            int day = int.Parse(arr[0]);
            int month = dt.Month;
            int year = dt.Year;
            if (arr.Length > 1)
               month = int.Parse(arr[1]);
            if (arr.Length > 2)
               year = int.Parse(arr[2]);

            try
            {
               dt = new DateTime(year, month, day);
            }
            catch (Exception)
            {
               dt = BuildDate_Alternative(strDate);
            }
         }
         return dt;
      }

      private DateTime BuildDate_Alternative(string strDate)
      {
         char[] dateSeparators = { '-', ',' };

         DateTime dt = DateTime.Today;
         if (strDate.Length > 0)
         {
            string[] arr = strDate.Split(dateSeparators);
            int day = int.Parse(arr[0]);
            int month = dt.Month;
            int year = dt.Year;
            if (arr.Length > 1)
            {
               day = int.Parse(arr[1]);
               month = int.Parse(arr[0]);
            }
            if (arr.Length > 2)
               year = int.Parse(arr[2]);

            dt = new DateTime(year, month, day);
         }
         return dt;
      }

      private void btnExport_Click(object sender, EventArgs e)
      {
         ExportData();
      }

      private void ExportData()
      {
         foreach (DataRow dr in dataSet1.Tables[0].Rows)
         {
            string statement = "INSERT INTO wydatki VALUES(";
            statement += "'" + dr["Payment"] + "',";
            statement += "'" + dr["Date"] + "',";
            statement += "" + dr["Amount"].ToString().Replace(',', '.') + ",";
            statement += "'" + dr["Category"] + "',";
            statement += "'" + dr["SubCategory"] + "',";
            statement += "'" + dr["Comment1"] + "',";
            statement += "'" + dr["Comment2"] + "');";

            if(!Conn.WorkOffline)
            {
               SqlOdbcExecution.ExecuteInsert(statement, Conn.Connection);
               BackupInsertingStatement(statement);
            }
            else
               WriteInsertingStatementToFile(ExportImportPath, statement);
         }

         dataSet1.Tables[0].Rows.Clear();
      }

      private void BackupInsertingStatement(string statement)
      {
         WriteInsertingStatementToFile(BackupPath, statement);
      }
      
      private void WriteInsertingStatementToFile(string filename, string statement)
      {
         using (StreamWriter writer = File.AppendText(filename))
         {
            writer.WriteLine(statement);
         }
      }

      private void Form1_KeyDown(object sender, KeyEventArgs e)
      {
         if (e.KeyCode == Keys.F1)
            ExportData();
         else if (e.KeyCode == Keys.F2)
            ShowReportsForm();
         else if (e.Control && e.KeyCode == Keys.D1)
            chkPayment.Checked = !chkPayment.Checked;
         else if (e.Control && e.KeyCode == Keys.D2)
            chkDate.Checked = !chkDate.Checked;
         else if (e.Control && e.KeyCode == Keys.D3)
            chkAmount.Checked = !chkAmount.Checked;
         else if (e.Control && e.KeyCode == Keys.D4)
            chkCategory.Checked = !chkCategory.Checked;
         else if (e.Control && e.KeyCode == Keys.D5)
            chkSubCategory.Checked = !chkSubCategory.Checked;
         else if (e.Control && e.KeyCode == Keys.D6)
            chkComment1.Checked = !chkComment1.Checked;
         else if (e.Control && e.KeyCode == Keys.D7)
            chkComment2.Checked = !chkComment2.Checked;
         else if (e.Control && e.KeyCode == Keys.F)
            ShowReportsForm(true);
         else if (e.KeyCode == Keys.F4)
            ImportStatements();
      }

      private void Form1_FormClosing(object sender, FormClosingEventArgs e)
      {
         dataSet1.WriteXml(c_tempFilename);
      }

      private void Form1_Load(object sender, EventArgs e)
      {
         try
         {
            dataSet1.ReadXml(c_tempFilename);
         }
         catch (FileNotFoundException) { }
         
         CheckForImport();
      }

      private void btnExit_Click(object sender, EventArgs e)
      {
         Application.Exit();
      }

      private void btnReports_Click(object sender, EventArgs e)
      {
         ShowReportsForm();
      }

      private void ShowReportsForm(bool withFind = false)
      {
         using (ReportingGrid reporting = new ReportingGrid(withFind))
         {
            reporting.Conn = Conn;
            reporting.ShowDialog();
         }
      }
      
      private List<string> importStatements = new List<string>();
      
      private void CheckForImport()
      {
         using (StreamReader reader = File.OpenText(ExportImportPath))
         {
            string statement;
            while((statement = reader.ReadLine()) != null)
            {
               importStatements.Add(statement);
            }
         }
         
         if(importStatements.Count > 0)
            toolStripStatusLabel.Text = string.Format("Found {0} rows for import", importStatements.Count);
      }
      
      private void ImportStatements()
      {
         List<string> nonInserted = new List<string>();
         foreach(string statement in importStatements)
         {
            if(!Conn.WorkOffline)
            {
               try
               {
                  SqlOdbcExecution.ExecuteInsert(statement, Conn.Connection);
               }
               catch(SqlExecutionException e)
               {
                  nonInserted.Add(statement);
                  MessageBox.Show(e.Message);
               }
               BackupInsertingStatement(statement);
            }
            else
            {
               MessageBox.Show(statement);
               nonInserted.Add(statement);
            }
         }
         
         //clear export/import file
         using(StreamWriter writer = File.CreateText(ExportImportPath))
         {
            //write lines that were not imported
            foreach(string statement in nonInserted)
               writer.WriteLine(statement);
         }
         
         toolStripStatusLabel.Text = string.Format("Imported {0} of {1} rows", importStatements.Count - nonInserted.Count, importStatements.Count);
      }
   }
}
